package com.nchuoj.question.controller;

import com.feign.config.enums.RedisHead;
import com.feign.message.Question2JudgeMessage;
import com.feign.pojo.JudgeTestCase;
import com.nchuoj.question.pojo.Question;
import com.nchuoj.question.pojo.TestCase;
import com.nchuoj.question.service.QuestionService;
import com.nchuoj.question.service.TestCaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * TODO
 *
 * @Description
 * @Author ZW
 * @Date 2022/12/24 19:26
 **/
@RestController
@RequestMapping("question")
@Slf4j
public class QuestionController {


    private final RedisTemplate<String, Object> redisTemplate;

    private final QuestionService questionService;

    private final TestCaseService testCaseService;

    private final RabbitTemplate rabbitTemplate;

    @Autowired
    public QuestionController(RedisTemplate<String, Object> redisTemplate, QuestionService questionService, TestCaseService testCaseService, RabbitTemplate rabbitTemplate) {
        this.redisTemplate = redisTemplate;
        this.questionService = questionService;
        this.testCaseService = testCaseService;
        this.rabbitTemplate = rabbitTemplate;
    }

    @GetMapping("feignTest/{data}")
    public String getTestData(@PathVariable("data") String test) {
        return test;
    }

    @GetMapping("question")
    public Question getQuestionById(@RequestParam Integer qid) {
        if (qid == null) {
            return null;
        }
        Question question;
        //判断redis中是否有缓存
        if (Boolean.FALSE.equals(redisTemplate.hasKey(RedisHead.QUESTION.getRedisHead() + qid))) {
            question = questionService.getQuestionById(qid);
            redisTemplate.opsForValue().set(RedisHead.QUESTION.getRedisHead() + qid, question);
        } else {
            question = (Question) redisTemplate.opsForValue().get(RedisHead.QUESTION.getRedisHead() + qid);
        }

        return question;
    }

    @PostMapping("submit")
    @SuppressWarnings("unchecked")
    public void submitCode2Judger(@RequestBody Map<String, Object> args) {
        if (args == null || args.isEmpty()) {
            return;
        }
        String code = Optional.ofNullable(args.get("code")).isPresent()
                ? String.valueOf(args.get("code")) : "";

        Integer userId = Optional.ofNullable(args.get("userid")).isPresent()
                ? Integer.parseInt(String.valueOf(args.get("userid"))) : -1;

        Integer qid = Optional.ofNullable(args.get("qid")).isPresent()
                ? Integer.parseInt(String.valueOf(args.get("qid"))) : -1;

        Integer questionSetId = Optional.ofNullable(args.get("questionSetId")).isPresent()
                ? Integer.parseInt(String.valueOf(args.get("questionSetId"))) : -1;

        List<JudgeTestCase> judgeTestCaseList = new ArrayList<>(8);
        List<TestCase> list;
        if (Boolean.FALSE.equals(redisTemplate.hasKey(RedisHead.TEST_CASE.getRedisHead() + qid))) {
            list = testCaseService.getTestCaseListByQid(qid);
        } else {
            list = (List<TestCase>) redisTemplate.opsForValue().get(RedisHead.TEST_CASE.getRedisHead() + qid);
        }

        Optional.ofNullable(list).ifPresent(li ->
                li.forEach(e ->
                        judgeTestCaseList.add(new JudgeTestCase(e.getId(), false, "", e.getScore(), 0, 0))));

        Question2JudgeMessage message = new Question2JudgeMessage(userId, qid, questionSetId, 0, code, judgeTestCaseList);
        log.info("message:{}", message);
        rabbitTemplate.convertAndSend("questionFanoutExchange", "", message);
    }


    /***
     * 通过题目id，查询改题目id下所有的测试用例
     * @param qid 题目id
     * @return 返回改题目下所有的测试用例
     */
    @GetMapping("getTestCase")
    @SuppressWarnings("unchecked")
    Map<String, List<TestCase>> getTestCase(@RequestParam Integer qid) {
        if (Objects.isNull(qid)) {
            return null;
        }
        HashMap<String, List<TestCase>> map = new HashMap<>(8);
        if (Boolean.FALSE.equals(redisTemplate.hasKey(RedisHead.TEST_CASE.getRedisHead() + qid))) {
            //TestCase 拿到的是一个List
            List<TestCase> testCaseList = testCaseService.getTestCaseListByQid(qid);
            Optional.ofNullable(testCaseList).ifPresent(list -> {
                redisTemplate.opsForValue().set(RedisHead.TEST_CASE.getRedisHead() + qid, testCaseList, 7, TimeUnit.DAYS);
                map.put(String.valueOf(qid), list);
            });
        } else {
            log.info("Redis has test case of {}", qid);
            map.put(String.valueOf(qid), (List<TestCase>) redisTemplate.opsForValue().get(RedisHead.TEST_CASE.getRedisHead() + qid));
        }
        log.info("Get test case list by qid :{}", map);
        return map;
    }


}
